'use strict';
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
const moment = require('moment');
const Decimal = require('decimal.js');
const UAParser = require('ua-parser-js');


module.exports = {
  /**
   * @return {String} result 盐
   */
  getSalt() {
    return Buffer.from(crypto.randomBytes(16)).toString('base64');
  },

  /**
   * 密码撒盐哈希
   * @param {String} password 密码明文
   * @param {String} salt 盐
   * @return {String} result 密码加盐哈希值
   */
  hashPassword(password, salt) {
    return crypto.pbkdf2Sync(password, salt, 5, 64, 'sha512').toString('base64');
  },

  /**
   * MD5 签名
   * @param {String} data 签名数据
   * @return {String} result
   */
  md5(data) {
    const result = crypto.createHash('md5').update(data).digest('hex');
    return result;
  },

  /**
   * HMAC 加密
   * @param {String} data 签名数据
   * @param {String} algorithm 算法
   * @param {String} secret 密钥
   * @return {String} result
   */
  hmac(data, algorithm, secret) {
    const result = crypto.createHmac(algorithm, secret).update(data).digest('base64');
    return result;
  },

  /**
   * base64 编码
   * @param {String} data 编码数据
   * @return {String} result
   */
  base64(data) {
    return Buffer.from(data).toString('base64');
  },

  /**
   * 生成 uuid
   * @return {String} uuid
   */
  uuid() {
    return uuidv4();
  },

  /**
   * 除法
   * @param {Number} a 被除数
   * @param {Number} b 除数
   * @param {Number} fixed 小数点长度
   */
  div(a, b, fixed) {
    const c = new Decimal(a).div(b);
    return c.toFixed(fixed);
  },

  /**
   * 生成订单号 prefix+时间
   * @param {*} prefix 前缀
   * @return {String} result
   */
  generateOrderNo(prefix) {
    prefix = prefix || '';
    const time = moment().format('YYYYMMDDHHmmss');
    return `${prefix}${time}`;
  },

  /**
   * 生成兑奖码
   * @return {String} code
   */
  generatePrizeCode() {
    let code = (Math.random() * 900000) || 100000;
    code = Number.parseInt(code).toString();
    return code;
  },

  /**
   * 解析 user-agent
   *
   * @param {String} user_agent user_agent
   */
  parseUserAgent(user_agent) {
    const parser = new UAParser(user_agent);
    return parser.getResult();
  },

  /**
   * 解密微信业务数据
   * @param {*} appid 敏感数据归属 appId，开发者可校验此参数与自身 appId 是否一致
   * @param {*} session_key 会话密钥
   * @param {*} encrypted_data 包括敏感数据在内的完整用户信息的加密数据
   * @param {*} iv 加密算法的初始向量
   */
  wxDecryptBizData(appid, session_key, encrypted_data, iv) {
    const sessionKey = Buffer.from(session_key, 'base64');
    const encryptedData = Buffer.from(encrypted_data, 'base64');
    iv = Buffer.from(iv, 'base64');
    let result = {};
    try {
      const decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv);
      // 设置自动 padding 为 true，删除填充补位
      decipher.setAutoPadding(true);
      let decode = decipher.update(encryptedData, 'binary', 'utf8');
      decode += decipher.final('utf8');
      result = JSON.parse(decode);
    } catch (error) {
      throw Error(error.message);
    }
    if (result.watermark.appid !== appid) throw Error('无效的 appid');
    return result;
  },

  /**
   * 内容签名
   * @param {String} content content
   */
  signature(content) {
    const hash = crypto.createHash('md5');
    const sign = hash.update(content).digest('hex');
    return sign;
  },
};
